package it.polito.connectedcar.util;

import it.polito.connectedcar.tcc.zone.TCCZone;
import it.polito.connectedcar.tcc.zone.TCCZoneImpl;
import it.polito.connectedcar.tcc.zone.TokenLink;
import it.polito.connectedcar.tcc.zone.TokenLinkList;
import it.polito.connectedcar.tcc.zone.ZoneToken;
import it.polito.connectedcar.vehicle.VehicleZone;

import java.awt.geom.Point2D;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * This class is used for testing. It creates a bunch of Zones along with their
 * Tokens and TokenLinks to be loaded and used by the system.
 * 
 * @author Nicola Aresta
 * 
 */
public class TestZones {

    private List<TCCZone> zones;

    private static TestZones testZones;

    public static synchronized TestZones getInstance() {
	if (testZones == null)
	    testZones = new TestZones();
	return testZones;
    }

    protected TestZones() {
	setup();
    }

    public VehicleZone getVehicleStartZoneToken(double xPos, double yPos) {
	for (TCCZone zone : zones) {
	    if (zone.getQuadrantIndex(xPos, yPos) != -1) {
		InetSocketAddress tccAddress = new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT);
		return new VehicleZone(tccAddress, zone.getT());
	    }
	}
	return null;
    }

    private void setup() {
	zones = new ArrayList<TCCZone>();
	TCCZoneImpl zone1 = new TCCZoneImpl(new ZoneToken("1111".getBytes()),
		new Point2D.Double(0, 550), new Point2D.Double(150, 250), 3, 3,1);
	TCCZoneImpl zone2 = new TCCZoneImpl(new ZoneToken("2222".getBytes()),
		new Point2D.Double(250, 150), new Point2D.Double(550, 0), 3, 3,1);
	TCCZoneImpl zone3 = new TCCZoneImpl(new ZoneToken("3333".getBytes()),
		new Point2D.Double(250, 900), new Point2D.Double(550, 650), 3,3, 1);
	TCCZoneImpl zone4 = new TCCZoneImpl(new ZoneToken("4444".getBytes()),
		new Point2D.Double(650, 550), new Point2D.Double(900, 250), 3,3, 1);
	TCCZoneImpl zone5 = new TCCZoneImpl(new ZoneToken("5555".getBytes()),
		new Point2D.Double(250, 550), new Point2D.Double(550, 250), 3,3, 1);

	List<TokenLink> tokenLinks_z1 = new ArrayList<TokenLink>();
	tokenLinks_z1.add(new TokenLink(new Point2D.Double(0, 250),
		new Point2D.Double(250, 0), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 6, 7, 8 }), new ZoneToken("2222".getBytes())));
	tokenLinks_z1.add(new TokenLink(new Point2D.Double(0, 800),
		new Point2D.Double(250, 550), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 1, 2 }), new ZoneToken("3333".getBytes())));
	tokenLinks_z1.add(new TokenLink(new Point2D.Double(150, 550),
		new Point2D.Double(350, 250), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 2, 5, 8 }), new ZoneToken("5555".getBytes())));
	zone1.setTokenLinkList(new TokenLinkList(tokenLinks_z1));

	List<TokenLink> tokenLinks_z2 = new ArrayList<TokenLink>();
	tokenLinks_z2.add(new TokenLink(new Point2D.Double(0, 250),
		new Point2D.Double(250, 0), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 3, 6 }), new ZoneToken(
			"1111".getBytes())));
	tokenLinks_z2.add(new TokenLink(new Point2D.Double(550, 250),
		new Point2D.Double(800, 0), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 2, 5, 8 }), new ZoneToken("4444".getBytes())));
	tokenLinks_z2.add(new TokenLink(new Point2D.Double(250, 350),
		new Point2D.Double(550, 150), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 1, 2 }), new ZoneToken("5555".getBytes())));
	zone2.setTokenLinkList(new TokenLinkList(tokenLinks_z2));

	List<TokenLink> tokenLinks_z3 = new ArrayList<TokenLink>();
	tokenLinks_z3.add(new TokenLink(new Point2D.Double(0, 800),
		new Point2D.Double(250, 550), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 3, 6 }), new ZoneToken("1111".getBytes())));
	tokenLinks_z3.add(new TokenLink(new Point2D.Double(550, 800),
		new Point2D.Double(800, 550), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 2, 5, 8 }), new ZoneToken("4444".getBytes())));
	tokenLinks_z3.add(new TokenLink(new Point2D.Double(250, 650),
		new Point2D.Double(550, 650), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 6, 7, 8 }), new ZoneToken("5555".getBytes())));
	zone3.setTokenLinkList(new TokenLinkList(tokenLinks_z3));

	List<TokenLink> tokenLinks_z4 = new ArrayList<TokenLink>();
	tokenLinks_z4.add(new TokenLink(new Point2D.Double(550, 250),
		new Point2D.Double(800, 0), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 6, 7, 8 }), new ZoneToken("2222".getBytes())));
	tokenLinks_z4.add(new TokenLink(new Point2D.Double(550, 800),
		new Point2D.Double(800, 550), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 1, 2 }), new ZoneToken("3333".getBytes())));
	tokenLinks_z4.add(new TokenLink(new Point2D.Double(450, 550),
		new Point2D.Double(650, 250), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 3, 6 }), new ZoneToken("5555".getBytes())));
	zone4.setTokenLinkList(new TokenLinkList(tokenLinks_z4));

	List<TokenLink> tokenLinks_z5 = new ArrayList<TokenLink>();
	tokenLinks_z5.add(new TokenLink(new Point2D.Double(50, 550),
		new Point2D.Double(250, 250), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 3, 6 }), new ZoneToken("1111".getBytes())));
	tokenLinks_z5.add(new TokenLink(new Point2D.Double(250, 250),
		new Point2D.Double(550, 50), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 6, 7, 8 }), new ZoneToken("2222".getBytes())));
	tokenLinks_z5.add(new TokenLink(new Point2D.Double(250, 750),
		new Point2D.Double(550, 550), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 0, 1, 2 }), new ZoneToken("3333".getBytes())));
	tokenLinks_z5.add(new TokenLink(new Point2D.Double(550, 550),
		new Point2D.Double(750, 250), new InetSocketAddress(
			Constants.TEST_TCC_ADDRESS_HOST,
			Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT), Arrays
			.asList(new Integer[] { 2, 5, 8 }), new ZoneToken("4444".getBytes())));
	zone5.setTokenLinkList(new TokenLinkList(tokenLinks_z5));

	zones.add(zone1);
	zones.add(zone2);
	zones.add(zone3);
	zones.add(zone4);
	zones.add(zone5);
    }

    public List<TCCZone> getTestTCCZones() {
	return zones;
    }

    public List<VehicleZone> getTestVehicleZones() {
	List<VehicleZone> zones = new ArrayList<VehicleZone>();

	InetSocketAddress tccAddress = new InetSocketAddress(
		Constants.TEST_TCC_ADDRESS_HOST,
		Constants.TEST_TCC_FROM_VEHICLE_ADDRESS_PORT);

	VehicleZone zone1 = new VehicleZone(tccAddress, new ZoneToken("1111".getBytes()));
	VehicleZone zone2 = new VehicleZone(tccAddress, new ZoneToken("2222".getBytes()));
	VehicleZone zone3 = new VehicleZone(tccAddress, new ZoneToken("3333".getBytes()));
	VehicleZone zone4 = new VehicleZone(tccAddress, new ZoneToken("4444".getBytes()));
	VehicleZone zone5 = new VehicleZone(tccAddress, new ZoneToken("5555".getBytes()));
	zones.add(zone1);
	zones.add(zone2);
	zones.add(zone3);
	zones.add(zone4);
	zones.add(zone5);
	return zones;
    }
}
